package com.deepwiki.service;

import com.deepwiki.config.OpenAIConfig;
import com.theokanning.openai.completion.chat.ChatCompletionRequest;
import com.theokanning.openai.completion.chat.ChatCompletionResult;
import com.theokanning.openai.completion.chat.ChatMessage;
import com.theokanning.openai.completion.chat.ChatMessageRole;
import com.theokanning.openai.service.OpenAiService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;

/**
 * OpenAI服务类
 */
@Service
public class OpenAIService {

    private static final Logger logger = LoggerFactory.getLogger(OpenAIService.class);
    
    private final OpenAIConfig openAIConfig;
    private final OpenAiService openAiService;

    @Autowired
    public OpenAIService(OpenAIConfig openAIConfig) {
        this.openAIConfig = openAIConfig;
        // 创建OpenAI服务实例，设置超时时间
        this.openAiService = new OpenAiService(openAIConfig.getApiKey(), Duration.ofMinutes(5));
    }

    /**
     * 生成文档内容
     *
     * @param prompt 提示词
     * @return 生成的内容
     */
    public String generateContent(String prompt) {
        try {
            logger.debug("开始生成内容，提示词长度: {}", prompt.length());
            
            List<ChatMessage> messages = new ArrayList<>();
            messages.add(new ChatMessage(ChatMessageRole.USER.value(), prompt));

            ChatCompletionRequest completionRequest = ChatCompletionRequest.builder()
                    .model(openAIConfig.getModel())
                    .messages(messages)
                    .maxTokens(openAIConfig.getMaxTokens())
                    .temperature(openAIConfig.getTemperature())
                    .build();

            ChatCompletionResult result = openAiService.createChatCompletion(completionRequest);
            
            if (result.getChoices() != null && !result.getChoices().isEmpty()) {
                String content = result.getChoices().get(0).getMessage().getContent();
                logger.debug("内容生成成功，返回内容长度: {}", content.length());
                return content;
            } else {
                logger.warn("OpenAI返回结果为空");
                return "";
            }
            
        } catch (Exception e) {
            logger.error("生成内容失败", e);
            throw new RuntimeException("生成内容失败: " + e.getMessage(), e);
        }
    }

    /**
     * 异步生成文档内容
     *
     * @param prompt 提示词
     * @return CompletableFuture包装的生成内容
     */
    public CompletableFuture<String> generateContentAsync(String prompt) {
        return CompletableFuture.supplyAsync(() -> generateContent(prompt));
    }

    /**
     * 生成目录结构
     *
     * @param codeFiles 代码文件内容
     * @param repositoryName 仓库名称
     * @return 生成的目录结构JSON
     */
    public String generateCatalogStructure(String codeFiles, String repositoryName) {
        try {
            String prompt = buildCatalogPrompt(codeFiles, repositoryName);
            String result = generateContent(prompt);
            
            // 提取JSON内容
            return extractJsonFromResponse(result);
            
        } catch (Exception e) {
            logger.error("生成目录结构失败", e);
            throw new RuntimeException("生成目录结构失败: " + e.getMessage(), e);
        }
    }

    /**
     * 构建目录生成提示词
     */
    private String buildCatalogPrompt(String codeFiles, String repositoryName) {
        return """
            You are an expert technical documentation specialist with advanced software development knowledge. Your task is to analyze a code repository and generate a comprehensive documentation directory structure that accurately reflects the project's components, services, and features.

            First, review the following information about the repository:

            <code_files>
            """ + codeFiles + """
            </code_files>

            <repository_name>
            """ + repositoryName + """
            </repository_name>

            Your goal is to create a documentation structure specifically tailored to this project, based on careful analysis of the provided code, README, and other project materials. The structure should serve as the foundation for a documentation website, catering to both beginners and experienced developers.

            Process:
            1. Create a hierarchical documentation structure that reflects the project's organization.
            2. Ensure the structure meets all the requirements listed below.
            3. Generate the final output in the specified JSON format.

            Requirements for the documentation structure:
            1. Include only sections that correspond to actual components, services, and features in the project.
            2. Use terminology consistent with the project code.
            3. Mirror the logical organization of the project in the structure.
            4. Cover every significant aspect of the project without omission.
            5. Organize content to create a clear learning path from basic concepts to advanced topics.
            6. Balance high-level overviews with detailed reference documentation.
            7. Include sections for getting started, installation, and basic usage.
            8. Provide dedicated sections for each major feature and service.
            9. Include API documentation sections for all public interfaces.
            10. Address configuration, customization, and extension points.
            11. Include troubleshooting and advanced usage sections where appropriate.
            12. Organize reference material in a logical, accessible manner.

            Insert your output content between the <documentation_structure></documentation_structure> tags as follows:

            <documentation_structure>
            {
              "items": [
                {
                  "title": "section-identifier",
                  "name": "Section Name",
                  "prompt": "Create comprehensive content for this section focused on [SPECIFIC PROJECT COMPONENT/FEATURE]. Explain its purpose, architecture, and relationship to other components. Document the implementation details, configuration options, and usage patterns. Include both conceptual overviews for beginners and technical details for experienced developers. Use terminology consistent with the codebase. Provide practical examples demonstrating common use cases. Document public interfaces, parameters, and return values. Include diagrams where appropriate to illustrate key concepts.",
                  "children": [
                    {
                      "title": "subsection-identifier",
                      "name": "Subsection Name",
                      "prompt": "Develop detailed content for this subsection covering [SPECIFIC ASPECT OF PARENT COMPONENT]. Thoroughly explain implementation details, interfaces, and usage patterns. Include concrete examples from the actual codebase. Document configuration options, parameters, and return values. Explain relationships with other components. Address common issues and their solutions. Make content accessible to beginners while providing sufficient technical depth for experienced developers."
                    }
                  ]
                }
              ]
            }
            </documentation_structure>
            """;
    }

    /**
     * 从响应中提取JSON内容
     */
    private String extractJsonFromResponse(String response) {
        // 提取<documentation_structure></documentation_structure>标签内的内容
        String structureStart = "<documentation_structure>";
        String structureEnd = "</documentation_structure>";
        
        int startIndex = response.indexOf(structureStart);
        int endIndex = response.indexOf(structureEnd);
        
        if (startIndex != -1 && endIndex != -1) {
            return response.substring(startIndex + structureStart.length(), endIndex).trim();
        }
        
        // 如果没有找到标签，尝试提取JSON代码块
        String jsonStart = "```json";
        String jsonEnd = "```";
        
        startIndex = response.indexOf(jsonStart);
        endIndex = response.lastIndexOf(jsonEnd);
        
        if (startIndex != -1 && endIndex != -1 && endIndex > startIndex) {
            return response.substring(startIndex + jsonStart.length(), endIndex).trim();
        }
        
        // 如果都没有找到，返回原始响应
        logger.warn("无法从响应中提取JSON结构，返回原始响应");
        return response;
    }

    /**
     * 生成单个文档内容
     *
     * @param prompt 文档生成提示词
     * @param codeContext 代码上下文
     * @param repositoryUrl 仓库URL
     * @return 生成的Markdown内容
     */
    public String generateDocumentContent(String prompt, String codeContext, String repositoryUrl) {
        try {
            String fullPrompt = buildDocumentPrompt(prompt, codeContext, repositoryUrl);
            return generateContent(fullPrompt);
            
        } catch (Exception e) {
            logger.error("生成文档内容失败", e);
            throw new RuntimeException("生成文档内容失败: " + e.getMessage(), e);
        }
    }

    /**
     * 使用完整提示词生成内容
     *
     * @param fullPrompt 完整的提示词（已经包含所有参数替换）
     * @return 生成的内容
     */
    public String generateWithPrompt(String fullPrompt) {
        try {
            logger.debug("使用提示词模板生成内容，提示词长度: {}", fullPrompt.length());
            return generateContent(fullPrompt);
            
        } catch (Exception e) {
            logger.error("使用提示词模板生成内容失败", e);
            throw new RuntimeException("使用提示词模板生成内容失败: " + e.getMessage(), e);
        }
    }

    /**
     * 构建文档生成提示词
     */
    private String buildDocumentPrompt(String prompt, String codeContext, String repositoryUrl) {
        return """
            You are a technical documentation expert. Based on the following information, generate comprehensive documentation content in Markdown format.

            Repository: """ + repositoryUrl + """

            Task: """ + prompt + """

            Code Context:
            """ + codeContext + """

            Requirements:
            1. Generate content in Markdown format
            2. Include practical examples from the actual codebase
            3. Explain concepts clearly for both beginners and experienced developers
            4. Use proper Markdown formatting with headers, code blocks, lists, etc.
            5. Include relevant code snippets where appropriate
            6. Provide clear explanations of functionality and usage
            7. Include configuration examples if applicable
            8. Add troubleshooting information when relevant

            Generate the documentation content:
            """;
    }
} 